package com.zfzs.post.modules.flow.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.zfzs.post.modules.flow.domain.FlowActiv;
import com.zfzs.post.modules.flow.repository.FlowActivRepository;
import com.zfzs.post.modules.flow.service.FlowActivService;
import com.zfzs.post.modules.flow.service.dto.FlowActivQueryCriteria;
import com.zfzs.post.modules.flow.service.mapper.FlowActivMapper;
import com.zfzs.post.utils.PageUtil;
import com.zfzs.post.utils.QueryHelp;
import com.zfzs.post.utils.StringUtils;
import com.zfzs.post.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author wq
 * @date 2019-10-21
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FlowActivServiceImpl implements FlowActivService {

    @Autowired
    private FlowActivRepository flowActivRepository;

    @Autowired
    private FlowActivMapper flowActivMapper;


    @Override
    public Object queryAll(FlowActivQueryCriteria criteria, Pageable pageable) {
        Page<FlowActiv> page = flowActivRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(flowActivMapper::toDto));
    }

    @Override
    public Object queryAll(FlowActivQueryCriteria criteria) {
        return flowActivMapper.toDto(flowActivRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    public FlowActiv findById(Long activId) {
        Optional<FlowActiv> flowActiv = flowActivRepository.findById(activId);
        ValidationUtil.isNull(flowActiv, "FlowActiv", "activId", activId);
        return flowActiv.get();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlowActiv create(FlowActiv resources) {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setActivId(snowflake.nextId());
        return flowActivRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(FlowActiv resources) {
        Optional<FlowActiv> optionalFlowActiv = flowActivRepository.findById(resources.getActivId());
        ValidationUtil.isNull(optionalFlowActiv, "FlowActiv", "id", resources.getActivId());
        FlowActiv flowActiv = optionalFlowActiv.get();
        flowActiv.copy(resources);
        flowActivRepository.save(flowActiv);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long activId) {
        flowActivRepository.deleteById(activId);
    }

    @Override
    public List<FlowActiv> findByAgentId(Long agentId) {
        return flowActivRepository.findByAgentId(agentId);
    }

    @Override
    public List<FlowActiv> findByAgentIdAndTime(Long agentId, String startDate, String endDate) {
        if (startDate == null && endDate == null) {
            return findByAgentId(agentId);
        } else {

            return flowActivRepository.findByAgentIdAndTime(agentId, startDate, endDate);
        }
    }

    @Override
    public List<FlowActiv> findByAgentIdAndSubIds(Long agentId, List<Long> ids, String startDate, String endDate) {
        if (StringUtils.isEmpty(startDate) && StringUtils.isEmpty(endDate)) {
            return flowActivRepository.findByAgentIdAndActivAgentIn(agentId, ids);
        } else {
            return flowActivRepository.findActivByAgentId(agentId, ids, startDate, endDate);
        }
    }

    @Override
    public List<FlowActiv> findByOwnerActiv(Long agentId, String startDate, String endDate) {
        if (StringUtils.isEmpty(startDate) && StringUtils.isEmpty(startDate)) {
            return flowActivRepository.findByOwnerActiv(agentId);
        } else {
            return flowActivRepository.findByOwnerActiv(agentId, startDate, endDate);
        }
    }

    @Override
    public List<Map<String, Object>> findInfoList(Long agentId, String startDate, String endDate, Integer pageNo) {
        Pageable pageable = PageRequest.of(pageNo, 15);

        List<Map<String, Object>> infoList;
        if (StringUtils.isEmpty(startDate) && StringUtils.isEmpty(endDate)) {
            infoList = flowActivRepository.findInfoList(agentId, pageable);
        } else {
            infoList = flowActivRepository.findInfoList(agentId, startDate, endDate, pageable);
        }

        return infoList;
    }

    @Override
    public List<FlowActiv> findBySn(String sn) {
        return flowActivRepository.findBySn(sn);
    }

    @Override
    public Page<FlowActiv> findPage(FlowActivQueryCriteria criteria, Integer page, Integer size) {

        Pageable pageable = PageRequest.of(page, size);

        Specification specification = (Specification) (root, query, cb) -> {

            if (criteria.getAgentIds() != null && !criteria.getAgentIds().isEmpty()) {
                query.where(root.get("agentId").in(criteria.getAgentIds()));
            }

            if (criteria.getActivAgentIds() != null && !criteria.getActivAgentIds().isEmpty()) {
                query.where(root.get("activAgent").in(criteria.getActivAgentIds()));
            }

            if(StringUtils.isNotBlank(criteria.getStartDate()) && StringUtils.isNotBlank(criteria.getEndDate())){
                query.where(cb.between(root.get("createTime").as(String.class),criteria.getStartDate(),criteria.getEndDate()));
            }

            query.orderBy(cb.desc(root.get("createTime")));
            return query.getRestriction();
        };
        return flowActivRepository.findAll(specification,pageable);
    }
}